<?php

namespace App\Console\Commands\OpenShop\Contract;

use App\Enums\OpenShop\InvestmentPromotion\ContractStatusEnum;
use App\Enums\OpenShop\InvestmentPromotion\UserContractEnum;
use App\Enums\OpenShop\MissionTemplateEnum;
use App\Enums\Workflow\WorkflowEnum;
use App\Models\Common\ConfigModel;
use App\Models\Kms\User\KmsUser;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserContractModel;
use App\Models\OpenShop\Shop\OpenShopHandleExpireShopHistoryModel;
use App\Models\OpenShop\Shop\OpenShopHandleExpireShopMainModel;
use App\Models\Renew\RenewOrder\RenewDeferOperateHistoryModel;
use App\Models\System\SystemNotifyCenterModel;
use App\Remote\Feishu\FeishuMsgRemote;
use App\Remote\Feishu\Tools\MsgTagBuild\ImgTagMsgBuild;
use App\Remote\Feishu\Tools\MsgTagBuild\TextTagMsgBuild;
use App\Remote\Feishu\Tools\TextMsgBuildTools;
use App\Remote\Rms\RmsShopRemote;
use App\Remote\Rms\RmsUserRemote;
use App\Service\Common\SendVoiceService;
use App\Service\Cruise\Shop\CruiseShopService;
use App\Service\OpenShop\Feishu\ConfigService;
use App\Service\OpenShop\Feishu\OrganizationManageService;
use App\Service\Renew\RenewOrderService;
use App\Service\System\SystemNotifyService;
use App\Service\Workflow\WorkflowOrderService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Kuafu\Nsq\NsqPublisher;

class HandleExpireShopCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'contract:handleExpireShop {orderNo?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '合同：临期门店预处理';

    /**
     * @var int  执行时间戳
     */
    public static int $time;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     * @throws Exception|GuzzleException
     */
    public function handle(): int
    {
        $orderNo = $this->input->getArgument("orderNo");
        if (config('app.env') == "pre" && empty($orderNo)) {
            $this->getOutput()->error("pre 环境禁止全量执行该脚本");
            exit("脚本停止执行" . PHP_EOL);
        }

        self::$time = time();
        //过期门店配置
        $expireShopConfig = ConfigService::getConfigDetail("openShop", "expiredShop")["value"];
        $voiceCloudSwitch = (bool)($expireShopConfig["voiceCloudSwitch"] ?? false);
        $appid            = ConfigModel::getFsConfigByPlatformNameOrgId('openShop', 0)['appId'] ?? '';
        $url              = "https://applink.feishu.cn/client/mini_program/open?appId={$appid}&mode=window-semi&relaunch=true&path=%s";

        $groupMsg = [
            "manager"  => [],
            "province" => []
        ];

        $errOrderNoGroup = [];
        OpenShopMainProcessModel::query()
                                ->when($orderNo, function ($query) use ($orderNo) {
                                    $query->where("orderNo", $orderNo);
                                })
                                ->where("childLocationOrder", 0)
                                ->where("nowStepStatus", MissionTemplateEnum::STEP_STATUS_999)
                                ->where("shopId", ">", 0)
                                ->with([
                                    "signOrderRel",
                                    "userIdentityCardRel",
                                    "userContractsRel",
                                    "userBaseInfoRel",
                                    "userExperienceRel",
                                    "checkAcceptRel"
                                ])
                                ->chunkById(100,
                                    function (Collection $collection) use (
                                        &$groupMsg,
                                        &$errOrderNoGroup,
                                        $url,
                                        $voiceCloudSwitch
                                    ) {
                                        //todo 遍历合同根据合同有效期判断是否创建续签工单
                                        $collection->each(function (OpenShopMainProcessModel $mainProcessModel) use (
                                            &$groupMsg,
                                            &$errOrderNoGroup,
                                            $url,
                                            $voiceCloudSwitch
                                        ) {
                                            try {
                                                if ($mainProcessModel->userContractsRel->isNotEmpty()) {
                                                    $this->getOutput()->info(
                                                        "--------------遍历订单:  {$mainProcessModel->orderNo}  -----------"
                                                    );
                                                    if ($mainProcessModel->userContractsRel->count() == 1) {
                                                        //合同只有一条  取当前一条
                                                        $userContractModel = $mainProcessModel->userContractsRel->first();
                                                    } else {
                                                        //存在多条 取出开店或者续签合同完成的合同
                                                        $userContractModel = $mainProcessModel->userContractsRel
                                                            ->where("detailStatus", ContractStatusEnum::COMPLETE)
                                                            ->whereIn("contractType",
                                                                OpenShopUserContractModel::OPEN_SHOP_CONTRACT_GROUP)
                                                            ->sortBy("id")->first();
                                                    }

                                                    if (empty($userContractModel)) {
                                                        //合同取出异常  丢入消息数组
                                                        array_push($errOrderNoGroup, $mainProcessModel->orderNo);
                                                    }

                                                    //todo 90天以内过期 => 生成续签工单，续签节点消息记录，续签消息推送
                                                    if (
                                                        $userContractModel->endTime <= strtotime("+90 day", self::$time)
                                                    ) {
                                                        //todo 门店合同续签，合同工单是否存在
                                                        $existsWorkOrder = OpenShopHandleExpireShopMainModel::query()
                                                                                                            ->where("orderNo",
                                                                                                                $userContractModel->orderNo)
                                                                                                            ->where("userContractId",
                                                                                                                $userContractModel->id)
                                                                                                            ->first();

                                                        if ($existsWorkOrder) {
                                                            $workOrderNo = $existsWorkOrder->workOrderNo;
                                                        } else {
                                                            //todo 初始化生成续签单
                                                            $flow        = (new WorkflowOrderService)->init(
                                                                WorkflowEnum::WORKFLOW_TYPE_OPEN_SHOP_RENEW,
                                                                $userContractModel->mainProcessRel->shopId
                                                            );
                                                            $workOrderNo = $flow->workflowNo;
                                                        }

                                                        //todo 写入过期门店数据关联表
                                                        $expireShopMainModel = OpenShopHandleExpireShopMainModel::query()
                                                                                                                ->firstOrCreate(
                                                                                                                    [
                                                                                                                        "orderNo"        => $userContractModel->orderNo,
                                                                                                                        "userContractId" => $userContractModel->id,
                                                                                                                    ],
                                                                                                                    [
                                                                                                                        "orderNo"           => $userContractModel->orderNo,
                                                                                                                        "workOrderNo"       => $workOrderNo,
                                                                                                                        "shopId"            => $mainProcessModel->shopId,
                                                                                                                        "shopCode"          => $userContractModel->signOrderRel->shopCode,
                                                                                                                        "contractStartTime" => $userContractModel->startTime,
                                                                                                                        "contractEndTime"   => $userContractModel->endTime,
                                                                                                                        "createdAt"         => self::$time
                                                                                                                    ]
                                                                                                                );

                                                        if ($expireShopMainModel->createdAt->timestamp == self::$time) {
                                                            $this->getOutput()->comment("第一次生成工单");
                                                        }

                                                        $type = OpenShopHandleExpireShopHistoryModel::getType($userContractModel);

                                                        if ($type > 0) {
                                                            //todo 创建处理节点记录
                                                            $expireShopHistoryModel = OpenShopHandleExpireShopHistoryModel::query()
                                                                                                                          ->firstOrCreate(
                                                                                                                              [
                                                                                                                                  "mainId" => $expireShopMainModel->id,
                                                                                                                                  "type"   => $type,
                                                                                                                              ],
                                                                                                                              ["createdAt" => self::$time]
                                                                                                                          );

                                                            //todo 第一次创建节点记录
                                                            if ($expireShopHistoryModel->createdAt->timestamp == self::$time) {
                                                                $this->getOutput()->comment(
                                                                    "第一次创建节点记录 : " . OpenShopHandleExpireShopHistoryModel::TYPE_TEXT_GROUP[$type]
                                                                );
                                                                //todo 构建省区消息数据
                                                                self::buildGroupMsg($groupMsg, $userContractModel);

                                                                //todo 获取门店店长用户信息
                                                                $rmsShopManagers = RmsUserRemote::getShopManagerUserByShopId(
                                                                        [],
                                                                        [$userContractModel->signOrderRel->shopCode],
                                                                        true
                                                                    )['lists'] ?? [];

                                                                $pushUidCollection    = collect($rmsShopManagers)->pluck("userId");
                                                                $pushMobileCollection = collect($rmsShopManagers)->pluck("mobile");

                                                                //todo 节点消息处理
                                                                self::handleTypeFunc(
                                                                    $type,
                                                                    $expireShopMainModel,
                                                                    $userContractModel,
                                                                    $pushUidCollection,
                                                                    $pushMobileCollection,
                                                                    $voiceCloudSwitch
                                                                );
                                                            }
                                                        }
                                                    }
                                                }
                                            } catch (Exception $exception) {
                                                logException("行执行报错", $exception, $mainProcessModel->toArray(), true,
                                                    true);
                                            }
                                        });
                                    });

        //督导信息推送
        self::sendManagerMsg($groupMsg["manager"], $url);
        //省总消息推送
        self::sendProvinceMsg($groupMsg["province"], $url);

        if (!empty($errOrderNoGroup)) {
            logInfo("存在异常的合同订单", collect($errOrderNoGroup), true, true);
        }
        return 0;
    }

    /**
     * 发送督导信息
     *
     * @param array $managerGroup
     * @param $url
     * @throws GuzzleException
     */
    public static function sendManagerMsg(array $managerGroup, $url)
    {
        //督导信息推送
        collect($managerGroup)->groupBy("managerId")->each(function ($managerGroup, $managerId) use ($url) {
            $fsUserDetail = KmsUser::query()->where("rmsUserId", $managerId)->first();
            if ($fsUserDetail && $fsUserDetail->openId) {
                $shopInfo            = RmsShopRemote::getShopInfosByCodes($managerGroup->pluck("shopCode")->toArray());
                $shopStr             = collect($shopInfo["shopList"])->map(function ($shop) {
                    return $shop["shopCode"] . "-" . $shop["name"];
                })->slice(0, 3)->implode(",");
                $msgTemplateContents = view()->file(
                    app_path("Remote/Feishu/FsTemplate/Renew") . "/RenewExpiredProvinceOrManagerMsgTemplate.blade.php",
                    [
                        "count"      => $managerGroup->count(),
                        "url"        => sprintf($url, urlencode("pages/renewal/list")),
                        "role"       => "督导",
                        "userOpenId" => $fsUserDetail->openId,
                        "shopDetail" => "{$shopStr}等{$managerGroup->count()}家"
                    ]
                )->render();

                try {
                    FeishuMsgRemote::getInstance()->sendInteractiveMsg(
                        $msgTemplateContents,
                        $fsUserDetail->userId
                    );
                } catch (Exception $exception) {
                    logException("飞书消息发送失败", $exception, $fsUserDetail->toArray(), true, true);
                }
            }
        });
    }

    /**
     * 省总消息推送
     *
     * @param array $provinceGroup
     * @param string $url
     * @throws GuzzleException
     */
    public static function sendProvinceMsg(array $provinceGroup, string $url)
    {
        collect($provinceGroup)->groupBy("provinceCode")->each(function ($provinceGroup, $provinceCode) use ($url
        ) {
            $organizationUser = OrganizationManageService::getProvinceInfoByProvinceCode($provinceCode);
            $rmsUserId        = attributeGet($organizationUser, "operationUid", null);
            if ($rmsUserId) {
                $fsUserDetail = KmsUser::query()->where("rmsUserId", $rmsUserId)->first();
                if ($fsUserDetail && $fsUserDetail->openId) {
                    $shopInfo            = RmsShopRemote::getShopInfosByCodes($provinceGroup->pluck("shopCode")
                                                                                            ->toArray());
                    $shopStr             = collect($shopInfo["shopList"])->map(function ($shop) {
                        return $shop["shopCode"] . "-" . $shop["name"];
                    })->slice(0, 3)->implode(",");
                    $msgTemplateContents = view()->file(
                        app_path("Remote/Feishu/FsTemplate/Renew") . "/RenewExpiredProvinceOrManagerMsgTemplate.blade.php",
                        [
                            "count"      => $provinceGroup->count(),
                            "url"        => sprintf($url, urlencode("pages/renewal/list")),
                            "role"       => "省总",
                            "userOpenId" => $fsUserDetail->openId,
                            "shopDetail" => "{$shopStr}等{$provinceGroup->count()}家"
                        ]
                    )->render();

                    try {
                        FeishuMsgRemote::getInstance()->sendInteractiveMsg(
                            $msgTemplateContents,
                            $fsUserDetail->userId
                        );
                    } catch (Exception $exception) {
                        logException("飞书消息发送失败", $exception, $fsUserDetail->toArray(), true, true);
                    }
                }
            }
        });
    }

    /**
     * 处理类型
     *
     * @param int $type
     * @param OpenShopHandleExpireShopMainModel $expireShopMainModel
     * @param OpenShopUserContractModel $userContractModel
     * @param Collection $pushUidCollection
     * @param Collection $pushMobileCollection
     * @param bool $voiceCloudSwitch
     * @throws GuzzleException
     */
    public static function handleTypeFunc(
        int $type,
        OpenShopHandleExpireShopMainModel $expireShopMainModel,
        OpenShopUserContractModel $userContractModel,
        Collection $pushUidCollection,
        Collection $pushMobileCollection,
        bool $voiceCloudSwitch
    ) {
        $formatEndDate = formatDateYmd($userContractModel->endTime) . " 23:59:59";
        switch ($type) {
            case OpenShopHandleExpireShopHistoryModel::TYPE_1://todo 90天消息推送
            case OpenShopHandleExpireShopHistoryModel::TYPE_2://todo 60天消息推送
            case OpenShopHandleExpireShopHistoryModel::TYPE_3://todo 30天消息推送
                //todo 店长消息推送
                $pushUidCollection->each(function ($uid) use (
                    $userContractModel,
                    $expireShopMainModel
                ) {
                    //todo 发送app消息
                    self::msgSend(
                        "您有1家门店待续签",
                        vsprintf(
                            "亲爱的夸父伙伴，门店编号：%s的合同有效期即将到期,请点击查看详情进行处理。感谢您的理解！",
                            [
                                $userContractModel->signOrderRel->shopCode . $userContractModel->mainProcessRel->userBaseInfoRel->shopName
                            ]
                        ),
                        $userContractModel->mainProcessRel->shopId,
                        $uid,
                        vsprintf("%s%s%s", [
                            config('webUrl.notify_web_cdn_url'),
                            "#/pages/work-order/renewal/renewal?workflowNo=",
                            $expireShopMainModel->workOrderNo
                        ])
                    );
                });
                //todo 发送语音短信
                if ($voiceCloudSwitch) {
                    $pushMobileCollection->each(function ($mobile
                    ) use (
                        $userContractModel
                    ) {
                        (new SendVoiceService())->sendVoiceCallByTts(
                            $mobile,
                            config('voiceCloud.templateCode.expireShopRenew'),
                            json_encode([
                                "shop" => $userContractModel->signOrderRel->shopCode . $userContractModel->mainProcessRel->userBaseInfoRel->shopName,
                                "desc" => "有效期即将到期"
                            ])
                        );
                    });
                }
                break;
            case OpenShopHandleExpireShopHistoryModel::TYPE_4://todo 到期当天消息推送
                //todo 店长消息推送
                $pushUidCollection->each(function ($uid) use (
                    $userContractModel,
                    $formatEndDate,
                    $expireShopMainModel
                ) {
                    self::msgSend(
                        "您有1家门店待续签",
                        vsprintf(
                            "亲爱的夸父伙伴，门店编号：%s的合同有效期即将到期。请在%s之前完成处理，感谢您的理解！（PS：如到期后还未完成处理，系统将会暂停订货通道）",
                            [
                                $userContractModel->signOrderRel->shopCode . $userContractModel->mainProcessRel->userBaseInfoRel->shopName,
                                $formatEndDate
                            ]
                        ),
                        $userContractModel->mainProcessRel->shopId,
                        $uid,
                        vsprintf("%s%s%s", [
                            config('webUrl.notify_web_cdn_url'),
                            "#/pages/work-order/renewal/renewal?workflowNo=",
                            $expireShopMainModel->workOrderNo
                        ])
                    );
                });
                //todo 语音电话通知
                if ($voiceCloudSwitch) {
                    $pushMobileCollection->each(function ($mobile) use (
                        $userContractModel
                    ) {
                        (new SendVoiceService())->sendVoiceCallByTts(
                            $mobile,
                            config('voiceCloud.templateCode.expireShopRenew'),
                            json_encode([
                                "shop" => $userContractModel->signOrderRel->shopCode . $userContractModel->mainProcessRel->userBaseInfoRel->shopName,
                                "desc" => "有效期即将到期"
                            ])
                        );
                    });
                }
                break;
            case OpenShopHandleExpireShopHistoryModel::TYPE_5://todo 到期次日消息推送
                //todo 获取门店有效延期记录
                $shopDefer = RenewDeferOperateHistoryModel::query()
                                                          ->where("shopId",
                                                              $userContractModel->mainProcessRel->shopId)
                                                          ->where("endTime", ">", time())
                                                          ->where("status", RenewDeferOperateHistoryModel::STATUS_0)
                                                          ->count();
                if (!$shopDefer) {
                    // 自动停收银
                    RmsShopRemote::updateShopFieldById(
                        $userContractModel->mainProcessRel->shopId,
                        ['cashRegisterStatus' => RmsShopRemote::SHOP_EXPIRED_OFF]
                    );
                    //停订货
                    (new NsqPublisher(config('nsq.default.address')))
                        ->pub('tiger.openShop.shopStatus.switch', [
                            'nsqEventTime'  => time(),
                            'shopId'        => $userContractModel->mainProcessRel->shopId,
                            'switch'        => 0, // 门店禁用关闭为 0
                            'operatorId'    => 0,
                            'operatorName'  => "系统",
                            'reason'        => "门店合约到期停用订货",
                            'operationTime' => time()
                        ]);
                }
                //todo 店长消息推送
                $pushUidCollection->each(function ($uid) use (
                    $userContractModel,
                    $expireShopMainModel
                ) {
                    self::msgSend(
                        "您有1家门店待续签",
                        vsprintf(
                            "亲爱的夸父伙伴，门店编号：%s的合同有效期已过期，目前已暂停订货通道，如7天后还未收到您的处理反馈，会暂停收银通道,请点击查看详情进行处理。感谢您的理解！",
                            [
                                $userContractModel->signOrderRel->shopCode . $userContractModel->mainProcessRel->userBaseInfoRel->shopName,
                            ]
                        ),
                        $userContractModel->mainProcessRel->shopId,
                        $uid,
                        vsprintf("%s%s%s", [
                            config('webUrl.notify_web_cdn_url'),
                            "#/pages/work-order/renewal/renewal?workflowNo=",
                            $expireShopMainModel->workOrderNo
                        ])
                    );

                });
                //todo 语音电话通知
                if ($voiceCloudSwitch) {
                    $pushMobileCollection->each(function ($mobile) use (
                        $userContractModel
                    ) {
                        (new SendVoiceService())->sendVoiceCallByTts(
                            $mobile,
                            config('voiceCloud.templateCode.expireShopRenew'),
                            json_encode([
                                "shop" => $userContractModel->signOrderRel->shopCode . $userContractModel->mainProcessRel->userBaseInfoRel->shopName,
                                "desc" => "有效期已过期"
                            ])
                        );
                    });
                }
                break;
        }
    }

    /**
     *  构建省区消息数据
     *
     * @param array $groupMsg
     * @param OpenShopUserContractModel $userContractModel
     */
    public static function buildGroupMsg(array &$groupMsg, OpenShopUserContractModel $userContractModel)
    {
        array_push($groupMsg["manager"], [
            "managerId" => $userContractModel->mainProcessRel->checkAcceptRel->managerId,
            "shopCode"  => $userContractModel->signOrderRel->shopCode,
        ]);
        array_push($groupMsg["province"], [
            "managerId"    => $userContractModel->mainProcessRel->checkAcceptRel->managerId,
            "shopCode"     => $userContractModel->signOrderRel->shopCode,
            "provinceCode" => $userContractModel->mainProcessRel->userBaseInfoRel->provinceCode
        ]);
    }

    /**
     * @param string $title
     * @param string $summary
     * @param int $shopId
     * @param int $merchantUserId
     * @param string $url
     */
    public static function msgSend(string $title, string $summary, int $shopId, int $merchantUserId, string $url)
    {
        // 向商家发送报名消息
        $notify = SystemNotifyService::save(
            false,
            $title,
            SystemNotifyCenterModel::NOTIFY_TYPE_3,
            SystemNotifyCenterModel::NOTIFY_TARGET_1,
            '',
            $title,
            $url,
            SystemNotifyCenterModel::METHOD_TYPE_AUTOMATIC,
            $summary,
            '',
            SystemNotifyCenterModel::IS_POPUP_ON,
            1,
            $shopId
        );
        SystemNotifyService::recordLog($notify, '创建消息');
        SystemNotifyService::preSend($notify->id, [$merchantUserId]);
    }

}
